package main

import (
	goflag "flag"
	"fmt"
	"github.com/go-redis/redis/v8"
	flag "github.com/spf13/pflag"
	"github.com/spf13/viper"
	"io/ioutil"
	"lotusmonitor"
	"lotusmonitor/logger"
	"os"
	"strconv"
	"sync"
)

var (
	h *bool
	v *bool
	//port string
	c *string
)


var version = "0.0.1"


type MonitorOpts struct {
	LogLevel string
	LotusHostAddr string
	LotusAuth string
	MQTopic string
}

type RedisOpts struct {
	Address string
	Password string
}

type ConfigOpts struct {
	Monitor MonitorOpts
	Redis RedisOpts
}

func init() {
	h = flag.BoolP("help","h", false, "this help")
	v = flag.BoolP("version","v", false, "show version and exit")
	c = flag.StringP("config","c", "config.yml", "set configuration `filename`")
	flag.Usage = usage
}

func filePathExists(filepath string) bool {
	s, err := os.Stat(filepath)
	if err != nil && os.IsNotExist(err) {
		return false
	}
	return !s.IsDir()
}

func ParseConfigFile(filepath string,opts *ConfigOpts) error {
	viper.SetConfigName("config")
	viper.SetConfigType("yaml")
	viper.AddConfigPath("/etc/lotusmonitor/")
	viper.AddConfigPath("$HOME/.lotusmonitor")
	viper.AddConfigPath(".")
	viper.AddConfigPath(filepath)
	if err := viper.ReadInConfig(); err != nil {
		return err
	}
	err := viper.Unmarshal(opts)
	if err != nil {
		return err
	}
	return nil
}

func usage() {
	fmt.Printf(`lotusmonitor version: 0.1.0
Usage: lotusmonitor [-hv] [-c filename]

Options:
`)
	flag.PrintDefaults()
}

func readOldHeight(filepath string) int64 {
	if !filePathExists(filepath) {
		return -1
	}
	content ,err := ioutil.ReadFile(filepath)
	if err != nil {
		return -1
	}
	height, err := strconv.ParseInt(string(content), 10, 64)
	if err != nil {
		return -1
	}
	return height
}

func writeHeight(filepath string, height int64) error {
	content := []byte(strconv.FormatInt(height, 10))
	err := ioutil.WriteFile(filepath, content, 0644)
	if err != nil {
		return err
	}
	return nil
}

func main() {
	flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
	flag.Parse()
	if *h {
		flag.Usage()
		os.Exit(0)
	}
	if *v {
		fmt.Printf("lotusmonitor version: %s\n",version)
		os.Exit(1)
	}
	var opts = &ConfigOpts{}
	err := ParseConfigFile(*c,opts)
	if err != nil {
		fmt.Printf("read config error: %s\n",err)
		os.Exit(1)
	}
	config := lotusmonitor.SyncerConfig{
		HostAddr: opts.Monitor.LotusHostAddr,
		AuthToken: opts.Monitor.LotusAuth,
	}
	rdb := redis.NewClient(&redis.Options{
		Addr: opts.Redis.Address,
		Password: opts.Redis.Password,
		DB:       0,
	})
	defer func() {
		if err := rdb.Close(); err != nil {
			fmt.Println(err)
			os.Exit(0)
		}
	}()
	height := readOldHeight("./height.txt")
	lger := logger.NewSTDLogger(logger.StringByLogLevel(opts.Monitor.LogLevel))
	mitor := lotusmonitor.NewMonitor(&config,*rdb)
	mitor.Lloger = lger
	var mutex sync.Mutex
	mutex.Lock()
	go mitor.SyncLoopAndCallback(height,opts.Monitor.MQTopic, func(height int64) error {
		return writeHeight("./height.txt",height)
	})
	mutex.Lock()
}